package cn.doways.api.service.serviceimpl;

import cn.doways.api.auth.JwtUsers;
import cn.doways.api.auth.JwtTokenUtil;
import cn.doways.api.dto.Userinfo;
import cn.doways.api.entity.Secret;
import cn.doways.api.entity.Student;
import cn.doways.api.entity.StudentCollegeDetail;
import cn.doways.api.entity.WeekTime;
import cn.doways.api.mapper.UsersMapper;
import cn.doways.api.service.RedisService;
import cn.doways.api.service.UsersService;
import cn.doways.api.utils.DateUtils;
import cn.doways.api.vo.PersonalCourseTableVO;
import cn.doways.api.vo.SchoolTimeListVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;


/**
 * @ClassName UsersServiceImpl
 * @Description //TODO
 * @Author shellming
 * @Date 2019-08-08 17:49
 **/
@Service
public class UsersServiceImpl implements UsersService {


    private UsersMapper usersMapper;
    private Student student;
    private Secret secret;
    private AuthenticationManager authenticationManager;
    private UserDetailsService userDetailsService;
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private RedisService redisService;


    @Autowired
    public UsersServiceImpl(UsersMapper usersMapper, Student student , Secret secret, AuthenticationManager authenticationManager, @Qualifier("jwtUserDetailsServiceImpl") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil) {
        this.usersMapper = usersMapper;
        this.student = student;
        this.secret = secret;
        this.authenticationManager = authenticationManager;
        this.userDetailsService = userDetailsService;
        this.jwtTokenUtil = jwtTokenUtil;
    }

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Override
    public Student getNameById(String id) {
        student = usersMapper.getNameById(id);
        return student;
    }

    @Override
    public int studentRegister(Secret secret) {
        if (usersMapper.hasStudent(secret.getId()) > 0) {
            return 0;
        }
        this.secret.setId(secret.getId());
        this.secret.setActiveStatus(1);
        this.secret.setPhoneNumber(secret.getPhoneNumber());
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        this.secret.setPasswordHash(encoder.encode(secret.getPasswordHash()));
        return usersMapper.saveStudent(this.secret);

    }

    @Override
    public String login(String username, String password) {
        UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
        final Authentication authentication = authenticationManager.authenticate(upToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        final UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        final String token = jwtTokenUtil.generateToken(userDetails);
        if (redisService.getValue(username)==null){
            redisService.setValue(username,token,3600);
            return token;
        }else{
            return redisService.getValue(username).toString();
        }


    }

    @Override
    public String refreash(String oldToken) {
        final String token = oldToken.substring(tokenHead.length());
        String username = jwtTokenUtil.getUsernameFromToken(token);
        JwtUsers user = (JwtUsers) userDetailsService.loadUserByUsername(username);
        if(user==null){
            return "行啊小伙伪造Token";
        }else if (jwtTokenUtil.canTokenBeRefreshed(user.getPhoneNumber())){
            final String refreshToken=jwtTokenUtil.refreshToken(token);
            redisService.setValue(username,refreshToken,3600);
            return refreshToken;
        }else {
            return "TokenExisted";
        }

    }

    @Override
    public int logout(String token) {
        final String outToken = token.substring(tokenHead.length());
        String username = jwtTokenUtil.getUsernameFromToken(outToken);
        JwtUsers user = (JwtUsers) userDetailsService.loadUserByUsername(username);
        if(user==null){
            return 1;
        }else if (redisService.getValue(user.getPhoneNumber())==null){
            return 2;
        }else {
            redisService.remove(user.getPhoneNumber());
            return 3;
        }
    }

    @Override
    public Userinfo getStudentInfo(String phoneNum){
        Userinfo<StudentCollegeDetail> userinfo=new Userinfo<StudentCollegeDetail>();
        try {
            userinfo = usersMapper.getUserInfo(phoneNum);
            userinfo.setData(usersMapper.getStudentDetailInfo(phoneNum));
        }catch (NullPointerException e){
            return null;
        }
        return userinfo;
    }

    @Override
    public int updateIntroduction(String id, String introduction) {
        return usersMapper.updateIntro(id,introduction);
    }

    @Override
    public int updateAvatar(String id,String avatarUrl) {
        return usersMapper.updateAvatar(id,avatarUrl);
    }

    @Override
    public List<PersonalCourseTableVO> getPersonalCourseTable(String id) {
        if (usersMapper.hasStudent(id)==0){
            return null;
        }else {
            Student student=usersMapper.getMajorClassidAndGrade(id);
            int week= LocalDateTime.now()
                                  .getDayOfWeek()
                                  .getValue();
            WeekTime weekTime=usersMapper.getWeekTime(1,2019,2020);
            int justWeek= DateUtils.getJustWeek(
                   DateUtils.asLocalDateTime(weekTime.getStartWeek()),
                   LocalDateTime.now()
            )+1;//48-48=0
            System.err.println(justWeek);
            return usersMapper.getPersonalCourseTable(
                    student.getGrade(),
                    week,
                    student.getMajor(),
                    student.getClassId(),
                    justWeek);
        }

    }

    @Override
    public List<SchoolTimeListVO> getWeekTimeList(String id, int yearOne, int yearTwo ,int term) {
        if (usersMapper.hasStudent(id)==0){
            return null;
        }
        else {
            Student student=usersMapper.getMajorClassidAndGrade(id);
            int maxkWeek=usersMapper.getMaxWeek(student.getGrade(),student.getMajor(),student.getClassId());
            WeekTime weekTime=usersMapper.getWeekTime(term,yearOne,yearTwo);
            List<SchoolTimeListVO> list=new ArrayList<SchoolTimeListVO>(maxkWeek);
            try {
                LocalDateTime localDateTime = DateUtils.asLocalDateTime(weekTime.getStartWeek());
                for(int i=0;i<maxkWeek;i++){
                    SchoolTimeListVO schoolTimeListVO=new SchoolTimeListVO();
                    schoolTimeListVO.setStartTime(localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli());
                    schoolTimeListVO.setEndTime(localDateTime.plusDays(7L).minusSeconds(1L).toInstant(ZoneOffset.of("+8")).toEpochMilli());
                    localDateTime=localDateTime.plusWeeks(1L);
                    schoolTimeListVO.setWeekNumber(i+1);
                    schoolTimeListVO.setType(1);
                    list.add(schoolTimeListVO);
                }
                return list;
            }catch (NullPointerException e){
                return null;
            }
        }
    }


}
